package project.parser.tokenizer;

import java.util.EnumSet;
import java.util.Set;

public enum TokenType {
	// not in map, but before DIV
	SKIP("a white space", null, "(?<" + skip_group() + ">\\s+|//.*$)"),
	// op symbols
	INC("++", "\\+\\+"), DECR("--"), ADD("+", "\\+"), SUB("-"), MUL("*", "\\*"), DIV("/"), MOD("%"), LEQ("<="), LTH("<"), GEQ(">="), GTH(">"),
	EQ("=="), UNEQ("!="), AND("&&", "\\&\\&"), OR("||", "\\|\\|"), NOT("!"), ASSGN("="),
	// delimiters
	OPEN_PAR("(", "\\("), CLOSED_PAR(")", "\\)"), OPEN_CURLY("{", "\\{"), CLOSED_CURLY("}", "\\}"), COMMA(","), COLON(":"), DOT(".", "\\."),
	// terminators
	SEMI_COL(";"),
	// keywords
	FALSE("false", true), TRUE("true", true), PRINT("print", true), IF("if", true), ELSE("else", true), WHILE("while", true),
	NUMBER_TYPE("number", true), BOOLEAN_TYPE("boolean", true), DEC("var", true), FUNCTION("function", true), RETURN("return", true),
	// not in map
	NUM("a number", null, "0[bB]" + "(?<" + bin_num_group() + ">[01]+)|(?<" + dec_num_group() + ">[0-9]+)"), IDENT("an identifier", null, null),
	BOOL("a Boolean value", null, null), RECORD("a Record value", null, null), RECORD_TYPE("record", null, null), EOF("end of file", null, null);

	private final String description;

	private final String token;

	private final String pattern;

	private final boolean isKey;

	public static final String DEC_NUM_GROUP = "decNum";

	private static String dec_num_group() {
		return DEC_NUM_GROUP;
	}

	public static final String BIN_NUM_GROUP = "binNum";

	private static String bin_num_group() {
		return BIN_NUM_GROUP;
	}

	public static final String SKIP_GROUP = "skip";

	private static String skip_group() {
		return SKIP_GROUP;
	}

	public static final String IDENT_HEAD_GROUP = "identHead";

	public static final String IDENT_TAIL_GROUP = "identTail";

	public static final String IDENT_HEAD = "(?<" + IDENT_HEAD_GROUP + ">[a-zA-Z_])";

	public static final String IDENT_TAIL = "(?<" + IDENT_TAIL_GROUP + ">[a-zA-Z0-9_]*)";

	public static final Set<TokenType> TYPE_GROUP = EnumSet.of(NUMBER_TYPE, BOOLEAN_TYPE);

	public static final Set<TokenType> BOOL_GROUP = EnumSet.of(FALSE, TRUE);

	public static final Set<TokenType> MUL_GROUP = EnumSet.of(MUL, DIV, MOD);

	public static final Set<TokenType> ADD_GROUP = EnumSet.of(ADD, SUB);

	public static final Set<TokenType> COMP_GROUP = EnumSet.of(LTH, LEQ, GTH, GEQ);

	public static final Set<TokenType> EQUAL_GROUP = EnumSet.of(EQ, UNEQ);

	public static final Set<TokenType> UNARY_GROUP = EnumSet.of(NOT, SUB, INC, DECR);

	private TokenType(String description, String token, String pattern, boolean isKey) {
		this.description = description;
		this.token = token;
		this.pattern = pattern;
		this.isKey = isKey;
	}

	private TokenType(String description, String token, String pattern) {
		this(description, token, pattern, false);
	}

	private TokenType(String pattern, boolean isKey) {
		this(pattern, pattern, pattern, isKey);
	}

	private TokenType(String token, String pattern) {
		this(token, token, pattern);
	}

	private TokenType(String pattern) {
		this(pattern, pattern);
	}

	@Override
	public String toString() {
		return description;
	}

	public String getPattern() {
		return pattern;
	}

	public String getToken() {
		return token;
	}

	public boolean isKeyword() {
		return isKey;
	}

}
